#include "utilities.h"
#include "../GL/glut.h"
#include "../jpeg/jpeglib.h"
#include <string.h>


GlobalUtils  globalUtils;


void DisplayFrameWF(){
	glDisable(GL_LIGHTING);

	glBegin(GL_LINES);
	
	glColor3f(0, 0.5f, 0);
	glVertex3f(0, 0, 0);
	glVertex3f(1, 0, 0);

	glColor3f(0.5f, 0, 0);
	glVertex3f(0, 0, 0);
	glVertex3f(0, 1, 0);

	glColor3f(0, 0, 0.5f);
	glVertex3f(0, 0, 0);
	glVertex3f(0, 0, 1);
	glEnd();
	glEnable(GL_LIGHTING);
}


void DisplayFrame(){
	glPushMatrix();
	glScalef(0.4f, 0.4f, 0.4f);
	glPushMatrix();
	glPushMatrix();
	glColor3f(1, 0, 0);
	glTranslatef(0, 1, 0); 
	glRotatef(-90, 1, 0, 0);
	gluCylinder(globalUtils.quadratic, 0.2f, 0.0f, 0.5f, 16, 16);
	glRotatef(180, 1, 0, 0);
	gluDisk(globalUtils.quadratic, 0.0f, 0.2f, 16, 16);	
	glPopMatrix();
	glRotatef(-90, 1, 0, 0);
	gluCylinder(globalUtils.quadratic, 0.1f, 0.1f, 1.2f, 16, 16);
	glPopMatrix();

	glPushMatrix();
	glPushMatrix();
	glColor3f(0, 1, 0);
	glTranslatef(1, 0, 0); 
	glRotatef(90, 0, 1, 0);
	gluCylinder(globalUtils.quadratic, 0.2f, 0.0f, 0.5f, 16, 16);
	glRotatef(-180, 0, 1, 0);
	gluDisk(globalUtils.quadratic, 0.0f, 0.2f, 16, 16);	
	glPopMatrix();
	glRotatef(90, 0, 1, 0);
	gluCylinder(globalUtils.quadratic, 0.1f, 0.1f, 1.2f, 16, 16);
	glPopMatrix();

	glPushMatrix();
	glColor3f(0, 0, 1);
	glTranslatef(0, 0, 1); 
	gluCylinder(globalUtils.quadratic, 0.2f, 0.0f, 0.5f, 16, 16);
	glRotatef(180, 0, 1, 0);
	gluDisk(globalUtils.quadratic, 0.0f, 0.2f, 16, 16);     
	glRotatef(-180, 0, 1, 0);
	glTranslatef(0, 0, -1);
	gluCylinder(globalUtils.quadratic, 0.1f, 0.1f, 1.2f, 16, 16);
	glPopMatrix();    

	glColor3f(1, 1, 0);
	
	gluSphere(globalUtils.quadratic, 0.15f, 16, 16);
	glPopMatrix();
}


void DisplayFrame(float red, float green, float blue){
	glPushMatrix();
	glScalef(0.4f, 0.4f, 0.4f);
	glPushMatrix();
	glPushMatrix();
	glColor3f(red, green, blue);
	glTranslatef(0, 1, 0); 
	glRotatef(-90, 1, 0, 0);
	gluCylinder(globalUtils.quadratic, 0.2f, 0.0f, 0.5f, 32, 32);
	glRotatef(180, 1, 0, 0);
	gluDisk(globalUtils.quadratic, 0.0f, 0.2f, 32, 32);	
	glPopMatrix();
	glRotatef(-90, 1, 0, 0);
	gluCylinder(globalUtils.quadratic, 0.1f, 0.1f, 1.2f, 32, 32);
	glPopMatrix();

	glPushMatrix();
	glPushMatrix();
	glTranslatef(1, 0, 0); 
	glRotatef(90, 0, 1, 0);
	gluCylinder(globalUtils.quadratic, 0.2f, 0.0f, 0.5f, 32, 32);
	glRotatef(-180, 0, 1, 0);
	gluDisk(globalUtils.quadratic, 0.0f, 0.2f, 32, 32);	
	glPopMatrix();
	glRotatef(90, 0, 1, 0);
	gluCylinder(globalUtils.quadratic, 0.1f, 0.1f, 1.2f, 32, 32);
	glPopMatrix();

	glPushMatrix();
	glTranslatef(0, 0, 1); 
	gluCylinder(globalUtils.quadratic, 0.2f, 0.0f, 0.5f, 32, 32);
	glRotatef(180, 0, 1, 0);
	gluDisk(globalUtils.quadratic, 0.0f, 0.2f, 32, 32);     
	glRotatef(-180, 0, 1, 0);
	glTranslatef(0, 0, -1);
	gluCylinder(globalUtils.quadratic, 0.1f, 0.1f, 1.2f, 32, 32);
	glPopMatrix();    

	
	gluSphere(globalUtils.quadratic, 0.15f, 32, 32);
	glPopMatrix();
}


void DisplayFrameWF(mtxlib::matrix44 &matr)
{
	const float scale = 1;

	glDisable(GL_LIGHTING);
	glPushMatrix();
	
	glTranslatef(matr[3][0], matr[3][1], matr[3][2]);

	glBegin(GL_LINES);
	for(int i = 0; i < 3; i++){
		glColor3f((i == 0 ? 1 : 0), (i == 1 ? 1 : 0), (i == 2 ? 1 : 0));
		glVertex3f(0, 0, 0);
		glVertex3f(scale * matr[i][0], scale * matr[i][1], scale * matr[i][2]);
	}
	glEnd();

	glPopMatrix();
	glEnable(GL_LIGHTING);
}


void DisplayDegFrame()
{
	glColor3f(0, 0, 1);
	glPushMatrix();
	glScalef(0.5, 0.5, 0.5);
	glTranslatef(0, 0, 1); 
	gluCylinder(globalUtils.quadratic, 0.2f, 0.0f, 0.5f, 16, 16);
	glRotatef(180, 0, 1, 0);
	gluDisk(globalUtils.quadratic, 0.0f, 0.2f, 16, 16);	
	glRotatef(-180, 0, 1, 0);
	glTranslatef(0, 0, -1);
	gluCylinder(globalUtils.quadratic, 0.1f, 0.1f, 1.2f, 16, 16);
	glPopMatrix();
}



// Render the inside of the unit box. Might be helpful during scene setup and debugging.
void DrawBox()
{
	float l = 1.0f;
	glFrontFace(GL_CW);
	glBegin(GL_QUADS);
			glNormal3f(0.0f, 0.0f, 1.0f);
			glVertex3f(-1.0f*l, 1.0f*l, -1.0f*l);
			glVertex3f(1.0f*l, 1.0f*l, -1.0f*l);
			glVertex3f(1.0f*l, -1.0f*l, -1.0f*l);
			glVertex3f(-1.0f*l, -1.0f*l, -1.0f*l);
			glNormal3f(0.0f, -1.0f, 0.0f);
			glVertex3f(-1.0f*l, 1.0f*l, -1.0f*l);
			glVertex3f(-1.0f*l, 1.0f*l, 1.0f*l);
			glVertex3f(1.0f*l, 1.0f*l, 1.0f*l);
			glVertex3f(1.0f*l, 1.0f*l, -1.0f*l);
			glNormal3f(0.0f, 0.0f, -1.0f);
			glVertex3f(-1.0f*l, -1.0f*l, 1.0f*l);
			glVertex3f(1.0f*l, -1.0f*l, 1.0f*l);
			glVertex3f(1.0f*l, 1.0f*l, 1.0f*l);
			glVertex3f(-1.0f*l, 1.0f*l, 1.0f*l);			
			glNormal3f(0.0f, 1.0f, 0.0f);
			glVertex3f(1.0f*l, -1.0f*l, -1.0f*l);
			glVertex3f(1.0f*l, -1.0f*l, 1.0f*l);
			glVertex3f(-1.0f*l, -1.0f*l, 1.0f*l);
			glVertex3f(-1.0f*l, -1.0f*l, -1.0f*l);
			glNormal3f(1.0f, 0.0f, 0.0f);
			glVertex3f(-1.0f*l, 1.0f*l, 1.0f*l);
			glVertex3f(-1.0f*l, 1.0f*l, -1.0f*l);
			glVertex3f(-1.0f*l, -1.0f*l, -1.0f*l);
			glVertex3f(-1.0f*l, -1.0f*l, 1.0f*l);
			glNormal3f(-1.0f, 0.0f, 0.0f);
			glVertex3f(1.0f*l, -1.0f*l, 1.0f*l);
			glVertex3f(1.0f*l, -1.0f*l, -1.0f*l);
			glVertex3f(1.0f*l, 1.0f*l, -1.0f*l);
			glVertex3f(1.0f*l, 1.0f*l, 1.0f*l);
	glEnd();
	glFrontFace(GL_CCW);
}

void DrawGrid(float startX, float endX, float startZ, float endZ, float step)
{
	glDisable(GL_LIGHTING);
	glBegin(GL_LINES);
	glNormal3f(0, 0, 1);
	for(float i = startX; i < endX - step/2; i += step)
	{
		glVertex3f(i, startZ, 0);
		glVertex3f(i, endZ, 0);
	}
	glVertex3f(endX, startZ, 0);
	glVertex3f(endX, endZ, 0);

	for(float i = startZ; i < endZ - step/2; i += step)
	{
		glVertex3f(startX, i, 0);
		glVertex3f(endX, i, 0);
	}
	glVertex3f(startX, endZ, 0);
	glVertex3f(endX, endZ, 0);
	glEnd();
	glEnable(GL_LIGHTING);
}

int ReadJpg(const char *filename, int *width, int *height, unsigned char **pixels, int *components)
{
	FILE *pFile;
	JSAMPARRAY pBuffer;
	int nRowSize;
	struct jpeg_error_mgr jerr;
	struct jpeg_decompress_struct cinfo;

	if ((pFile = fopen(filename, "rb"))==NULL)
		return 0;
	cinfo.err = jpeg_std_error(&jerr);
	jpeg_create_decompress(&cinfo);
	jpeg_stdio_src(&cinfo, pFile);
	jpeg_read_header(&cinfo, TRUE);
	jpeg_start_decompress(&cinfo);
	*width		= cinfo.output_width == 0? cinfo.out_color_components : cinfo.output_width;
	*height		= cinfo.output_height;
	*components = cinfo.output_components;
	*pixels		= new unsigned char [cinfo.output_components * *width * *height];
	nRowSize = *width * cinfo.output_components;
	pBuffer = (*cinfo.mem->alloc_sarray)
		((j_common_ptr)&cinfo, JPOOL_IMAGE, nRowSize, 1);
	unsigned char *pixels_row = *pixels+nRowSize * (*height-1);
	while (cinfo.output_scanline < cinfo.output_height) {
		jpeg_read_scanlines(&cinfo, pBuffer, 1);
		memcpy(pixels_row, (void*)(pBuffer[0]), nRowSize);
		pixels_row -= nRowSize;
	}
	jpeg_finish_decompress(&cinfo);
	jpeg_destroy_decompress(&cinfo);
	fclose(pFile);
	return 1;
}